﻿using System;

namespace Minecraft.Map.Converters
{
	public class MapImageConverter : NamedBinaryTag.Converters.TagPathValueConverter
	{
#if !SILVERLIGHT
		private static System.Windows.Media.Imaging.BitmapPalette palette;
#else
		private static int[] colors;
#endif

		static MapImageConverter()
		{
			string[] textColors = "#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#FF405A1C,#FF4E6E22,#FF5B8028,#FF4E6E22,#FF7D7652,#FF999064,#FFB1A775,#FF999064,#FF545454,#FF676767,#FF787878,#FF676767,#FF810000,#FF9E0000,#FFB70000,#FF9E0000,#FF505081,#FF63639E,#FF7373B7,#FF63639E,#FF545454,#FF676767,#FF787878,#FF676767,#FF003E00,#FF004C00,#FF005900,#FF004C00,#FF818181,#FF9E9E9E,#FFB7B7B7,#FF9E9E9E,#FF52555D,#FF656771,#FF767984,#FF656771,#FF5D3518,#FF71411D,#FF834C22,#FF71411D,#FF393939,#FF454545,#FF505050,#FF454545,#FF202081,#FF27279E,#FF2E2EB7,#FF27279E,#FF342A19,#FF40331F,#FF4B3C24,#FF40331F,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF,#00FFFFFF".Split(',');
#if !SILVERLIGHT
			System.Collections.Generic.List<System.Windows.Media.Color> colors = new System.Collections.Generic.List<System.Windows.Media.Color>();
			for (int i = 0; i < textColors.Length; i++)
			{
				byte a = System.Convert.ToByte(textColors[i].Substring(1, 2), 16);
				byte r = System.Convert.ToByte(textColors[i].Substring(3, 2), 16);
				byte g = System.Convert.ToByte(textColors[i].Substring(5, 2), 16);
				byte b = System.Convert.ToByte(textColors[i].Substring(7, 2), 16);
				colors.Add(System.Windows.Media.Color.FromArgb(a, r, g, b));
			}
			palette = new System.Windows.Media.Imaging.BitmapPalette(colors);
#else
			colors = new int[textColors.Length];
			for (int i = 0; i < textColors.Length; i++)
				colors[i] = System.Convert.ToInt32(textColors[i].Substring(1), 16);
#endif
		}

		public override object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
		{
			object convertedValue = base.Convert(value, targetType, parameter, culture);
			if ((convertedValue == parameter) || (convertedValue == (object)MissingParameter) || (convertedValue == null))
			{
				byte[] emptyData = new byte[1] { 0 };
#if !SILVERLIGHT
				return System.Windows.Media.Imaging.BitmapSource.Create(1, 1, 96, 96, System.Windows.Media.PixelFormats.Indexed8, System.Windows.Media.Imaging.BitmapPalettes.Gray256, emptyData, 1);
#else
				return CreateBitmap(1, 1, emptyData);
#endif
			}
			short width = 0;
			short height = 0;
			byte[] data = null;
			string param = parameter as string;
			object result = base.Convert(value, targetType, param + "." + WidthName, culture);
			if (result is short)
				width = (short)result;
			result = base.Convert(value, targetType, param + "." + HeightName, culture);
			if (result is short)
				height = (short)result;
			result = base.Convert(value, targetType, param + "." + DataName, culture);
			if (result is byte[])
				data = (byte[])result;
			if ((width == 0) || (height == 0))
				return null;
			if (data.Length != width * height)
				throw new Exception("Provided image data does not match the image size.");
#if !SILVERLIGHT
			System.Windows.Media.Imaging.BitmapSource image = System.Windows.Media.Imaging.BitmapSource.Create(width, height, 96, 96, System.Windows.Media.PixelFormats.Indexed8, palette, data, width);
			// System.Windows.Media.Imaging.PngBitmapEncoder enc = new System.Windows.Media.Imaging.PngBitmapEncoder();
			// enc.Interlace = System.Windows.Media.Imaging.PngInterlaceOption.Off;
			// enc.Frames.Add(System.Windows.Media.Imaging.BitmapFrame.Create(image));
			// using (System.IO.FileStream file = new System.IO.FileStream(@"Z:\output.png", System.IO.FileMode.Create, System.IO.FileAccess.Write, System.IO.FileShare.None))
				// enc.Save(file);
			return image;
#else
			return CreateBitmap(width, height, data);
#endif
		}

#if SILVERLIGHT
		private System.Windows.Media.Imaging.BitmapSource CreateBitmap(int width, int height, byte[] data)
		{
			System.Windows.Media.Imaging.WriteableBitmap bitmap = new System.Windows.Media.Imaging.WriteableBitmap(width, height);
			int[] output = bitmap.Pixels;
			for (int i = 0; i < data.Length; i++)
			{
				// uint v = (uint)data[i] + ((uint)data[i] << 8) + ((uint)data[i] << 16) + (uint)0xFF << 24;
				//unchecked { output[i] = (int)v; }
				// output[i] = data[i] * 0x01010001 + 0xFF << 8;
				// unchecked { output[i] = (int)0xFFFFFF00; } // 24+ = A, 16+ = R, 8+ = V, 0+ = 
				output[i] = colors[data[i]];
			}
			return bitmap;
		}
#endif

		public string WidthName { get; set; }
		public string HeightName { get; set; }
		public string DataName { get; set; }
	}
}
